from PySide6.QtWidgets import QWidget, QVBoxLayout, QLabel
from PySide6.QtCore import QTimer, Qt, QThread, Signal, QPointF
from PySide6.QtGui import QPainter, QColor, QPen, QBrush, QPixmap, QFont, QWheelEvent, QMouseEvent
import math
import random


class NetworkMapWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMinimumSize(800, 400)
        self.connections = []

        # 交互控制变量
        self.scale_factor = 1.0
        self.min_scale = 0.3
        self.max_scale = 3.0
        self.offset_x = 0
        self.offset_y = 0
        self.is_dragging = False
        self.last_mouse_pos = QPointF()
        self.sphere_mode = False  # 球体模式

        # 减少动画更新频率
        self.animation_timer = QTimer()
        self.animation_timer.timeout.connect(self.update_animation)
        self.animation_timer.start(300)  # 300ms更新一次
        self.animation_phase = 0

        # 世界主要城市坐标 (经度, 纬度)
        self.major_cities = {
            '北京': (116.4074, 39.9042),
            '上海': (121.4737, 31.2304),
            '深圳': (114.1694, 22.3193),
            '东京': (139.6503, 35.6762),
            '首尔': (126.978, 37.5665),
            '新加坡': (103.8198, 1.3521),
            '悉尼': (151.2093, -33.8688),
            '纽约': (-74.006, 40.7128),
            '洛杉矶': (-118.2437, 34.0522),
            '伦敦': (-0.1278, 51.5074),
            '巴黎': (2.3522, 48.8566),
            '法兰克福': (8.6821, 50.1109),
            '莫斯科': (37.6176, 55.7558),
            '孟买': (72.8777, 19.0760),
            '开普敦': (18.4241, -33.9249),
            '圣保罗': (-46.6333, -23.5505),
            '墨西哥城': (-99.1332, 19.4326),
        }

        # 修改样式，确保背景是深色的
        self.setStyleSheet("""
            NetworkMapWidget {
                background-color: #1a1a2e;
                border: 2px solid #3d4465;
                border-radius: 12px;
            }
        """)

        # 设置背景色
        self.setAutoFillBackground(True)
        palette = self.palette()
        palette.setColor(self.backgroundRole(), QColor(26, 26, 46))
        self.setPalette(palette)

        # 启用鼠标跟踪
        self.setMouseTracking(True)

    def update_connections(self, connections):
        """更新网络连接数据"""
        self.connections = connections[:15]  # 限制显示数量
        self.update()

    def update_animation(self):
        """更新动画相位"""
        self.animation_phase = (self.animation_phase + 1) % 60
        self.update()

    def coord_to_pixel(self, lon, lat):
        """将经纬度转换为像素坐标"""
        if self.sphere_mode:
            return self.coord_to_sphere_pixel(lon, lat)
        else:
            return self.coord_to_flat_pixel(lon, lat)

    def coord_to_flat_pixel(self, lon, lat):
        """平面地图投影"""
        width = self.width() - 40
        height = self.height() - 40

        # 墨卡托投影的简化版本
        x = ((lon + 180) / 360) * width + 20
        y = ((90 - lat) / 180) * height + 20

        # 应用缩放和平移
        center_x = self.width() / 2
        center_y = self.height() / 2

        x = (x - center_x) * self.scale_factor + center_x + self.offset_x
        y = (y - center_y) * self.scale_factor + center_y + self.offset_y

        return int(x), int(y)

    def coord_to_sphere_pixel(self, lon, lat):
        """球体投影"""
        # 球体半径
        radius = min(self.width(), self.height()) * 0.35 * self.scale_factor
        center_x = self.width() / 2 + self.offset_x
        center_y = self.height() / 2 + self.offset_y

        # 转换为弧度
        lon_rad = math.radians(lon)
        lat_rad = math.radians(lat)

        # 简单的正交投影
        x = center_x + radius * math.cos(lat_rad) * math.sin(lon_rad)
        y = center_y - radius * math.sin(lat_rad)

        # 检查点是否在球体前面（简化处理）
        z = math.cos(lat_rad) * math.cos(lon_rad)
        if z < 0:  # 在球体背面
            return None, None

        return int(x), int(y)

    def wheelEvent(self, event: QWheelEvent):
        """鼠标滚轮事件 - 缩放"""
        # 获取滚轮滚动方向
        delta = event.angleDelta().y()

        # 计算缩放因子
        zoom_factor = 1.1 if delta > 0 else 1.0 / 1.1
        new_scale = self.scale_factor * zoom_factor

        # 限制缩放范围
        if self.min_scale <= new_scale <= self.max_scale:
            # 获取鼠标位置
            mouse_pos = event.position()

            # 计算缩放中心
            center_x = self.width() / 2
            center_y = self.height() / 2

            # 调整偏移量，使缩放以鼠标位置为中心
            self.offset_x = mouse_pos.x() - (mouse_pos.x() - self.offset_x) * zoom_factor
            self.offset_y = mouse_pos.y() - (mouse_pos.y() - self.offset_y) * zoom_factor

            self.scale_factor = new_scale

            # 检查是否需要切换到球体模式
            if self.scale_factor <= self.min_scale + 0.1:
                self.sphere_mode = True
            else:
                self.sphere_mode = False

            self.update()

    def mousePressEvent(self, event: QMouseEvent):
        """鼠标按下事件"""
        if event.button() == Qt.MouseButton.LeftButton:
            self.is_dragging = True
            self.last_mouse_pos = event.position()
            self.setCursor(Qt.CursorShape.ClosedHandCursor)

    def mouseMoveEvent(self, event: QMouseEvent):
        """鼠标移动事件"""
        if self.is_dragging:
            # 计算鼠标移动距离
            delta = event.position() - self.last_mouse_pos

            # 更新偏移量
            self.offset_x += delta.x()
            self.offset_y += delta.y()

            # 更新鼠标位置
            self.last_mouse_pos = event.position()

            self.update()

    def mouseReleaseEvent(self, event: QMouseEvent):
        """鼠标释放事件"""
        if event.button() == Qt.MouseButton.LeftButton:
            self.is_dragging = False
            self.setCursor(Qt.CursorShape.ArrowCursor)

    def mouseDoubleClickEvent(self, event: QMouseEvent):
        """双击重置视图"""
        self.scale_factor = 1.0
        self.offset_x = 0
        self.offset_y = 0
        self.sphere_mode = False
        self.update()

    def paintEvent(self, event):
        """绘制地图和网络连接"""
        painter = QPainter(self)
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)

        # 填充背景色
        if self.sphere_mode:
            # 球体模式背景
            painter.fillRect(self.rect(), QColor(10, 10, 30))
        else:
            painter.fillRect(self.rect(), QColor(26, 26, 46))

        if self.sphere_mode:
            self.draw_sphere_mode(painter)
        else:
            self.draw_flat_mode(painter)

        # 绘制控制信息
        self.draw_controls_info(painter)

    def draw_flat_mode(self, painter):
        """绘制平面地图模式"""
        # 绘制背景网格
        self.draw_grid(painter)

        # 绘制世界地图轮廓
        self.draw_world_outline(painter)

        # 绘制主要城市
        self.draw_cities(painter)

        # 绘制网络连接
        self.draw_connections(painter)

    def draw_sphere_mode(self, painter):
        """绘制球体模式"""
        # 绘制球体
        self.draw_sphere(painter)

        # 绘制球体上的城市
        self.draw_sphere_cities(painter)

        # 绘制球体上的连接
        self.draw_sphere_connections(painter)

    def draw_sphere(self, painter):
        """绘制地球球体"""
        radius = min(self.width(), self.height()) * 0.35 * self.scale_factor
        center_x = self.width() / 2 + self.offset_x
        center_y = self.height() / 2 + self.offset_y

        # 绘制球体阴影
        shadow_offset = 5
        painter.setBrush(QBrush(QColor(0, 0, 0, 100)))
        painter.setPen(Qt.PenStyle.NoPen)
        painter.drawEllipse(int(center_x - radius + shadow_offset),
                            int(center_y - radius + shadow_offset),
                            int(radius * 2), int(radius * 2))

        # 绘制球体主体
        painter.setBrush(QBrush(QColor(30, 60, 120, 200)))
        painter.setPen(QPen(QColor(100, 150, 255, 150), 2))
        painter.drawEllipse(int(center_x - radius), int(center_y - radius),
                            int(radius * 2), int(radius * 2))

        # 绘制经纬线
        painter.setPen(QPen(QColor(100, 150, 255, 80), 1))

        # 经线
        for lon in range(-180, 181, 30):
            points = []
            for lat in range(-90, 91, 10):
                x, y = self.coord_to_sphere_pixel(lon, lat)
                if x is not None and y is not None:
                    # 检查点是否在球体内
                    dist = math.sqrt((x - center_x) ** 2 + (y - center_y) ** 2)
                    if dist <= radius:
                        points.append((x, y))

            # 绘制经线
            for i in range(len(points) - 1):
                painter.drawLine(points[i][0], points[i][1],
                                 points[i + 1][0], points[i + 1][1])

        # 纬线
        for lat in range(-90, 91, 30):
            points = []
            for lon in range(-180, 181, 10):
                x, y = self.coord_to_sphere_pixel(lon, lat)
                if x is not None and y is not None:
                    # 检查点是否在球体内
                    dist = math.sqrt((x - center_x) ** 2 + (y - center_y) ** 2)
                    if dist <= radius:
                        points.append((x, y))

            # 绘制纬线
            for i in range(len(points) - 1):
                painter.drawLine(points[i][0], points[i][1],
                                 points[i + 1][0], points[i + 1][1])

    def draw_sphere_cities(self, painter):
        """绘制球体上的城市"""
        radius = min(self.width(), self.height()) * 0.35 * self.scale_factor
        center_x = self.width() / 2 + self.offset_x
        center_y = self.height() / 2 + self.offset_y

        for city, (lon, lat) in self.major_cities.items():
            x, y = self.coord_to_sphere_pixel(lon, lat)

            if x is not None and y is not None:
                # 检查点是否在球体内
                dist = math.sqrt((x - center_x) ** 2 + (y - center_y) ** 2)
                if dist <= radius:
                    # 绘制城市点
                    painter.setBrush(QBrush(QColor(255, 255, 100, 200)))
                    painter.setPen(QPen(QColor(255, 255, 255, 255), 1))
                    painter.drawEllipse(x - 3, y - 3, 6, 6)

                    # 主要城市显示名称
                    if city in ['北京', '纽约', '伦敦', '东京']:
                        painter.setPen(QPen(QColor(255, 255, 255, 200)))
                        painter.setFont(QFont("Arial", 9))
                        painter.drawText(x + 6, y - 2, city)

    def draw_sphere_connections(self, painter):
        """绘制球体上的连接"""
        if not self.connections:
            return

        radius = min(self.width(), self.height()) * 0.35 * self.scale_factor
        center_x = self.width() / 2 + self.offset_x
        center_y = self.height() / 2 + self.offset_y

        # 北京作为默认源点
        source_x, source_y = self.coord_to_sphere_pixel(116.4074, 39.9042)

        if source_x is None or source_y is None:
            return

        display_connections = self.connections[:6]

        for i, conn in enumerate(display_connections):
            try:
                target_lon = conn.get('longitude', 0)
                target_lat = conn.get('latitude', 0)

                if target_lon == 0 and target_lat == 0:
                    city_coords = random.choice(list(self.major_cities.values()))
                    target_lon, target_lat = city_coords

                target_x, target_y = self.coord_to_sphere_pixel(target_lon, target_lat)

                if target_x is None or target_y is None:
                    continue

                # 检查两点是否都在球体前面
                source_dist = math.sqrt((source_x - center_x) ** 2 + (source_y - center_y) ** 2)
                target_dist = math.sqrt((target_x - center_x) ** 2 + (target_y - center_y) ** 2)

                if source_dist <= radius and target_dist <= radius:
                    # 设置连接线样式
                    if conn.get('status') == 'ESTABLISHED':
                        line_color = QColor(0, 255, 100, 180)
                        dot_color = QColor(0, 255, 100, 220)
                    else:
                        line_color = QColor(255, 100, 100, 150)
                        dot_color = QColor(255, 100, 100, 200)

                    # 绘制弧形连接线（简化为直线）
                    painter.setPen(QPen(line_color, 2))
                    painter.drawLine(source_x, source_y, target_x, target_y)

                    # 绘制动画效果
                    if i < 3:
                        progress = (self.animation_phase + i * 15) % 60 / 60.0
                        anim_x = source_x + (target_x - source_x) * progress
                        anim_y = source_y + (target_y - source_y) * progress

                        painter.setBrush(QBrush(dot_color))
                        painter.setPen(Qt.PenStyle.NoPen)
                        painter.drawEllipse(int(anim_x - 2), int(anim_y - 2), 4, 4)

                    # 绘制目标点
                    painter.setBrush(QBrush(QColor(255, 255, 0, 200)))
                    painter.setPen(QPen(QColor(255, 255, 255, 200), 1))
                    painter.drawEllipse(target_x - 3, target_y - 3, 6, 6)

            except Exception as e:
                print(f"绘制球体连接时出错: {e}")
                continue

    def draw_grid(self, painter):
        """绘制背景网格"""
        painter.setPen(QPen(QColor(255, 255, 255, 20), 1))

        width = self.width()
        height = self.height()

        # 绘制网格线
        grid_size = int(60 * self.scale_factor)
        for i in range(-width, width * 2, grid_size):
            x = i + int(self.offset_x) % grid_size
            if 0 <= x <= width:
                painter.drawLine(x, 0, x, height)

        grid_size = int(40 * self.scale_factor)
        for i in range(-height, height * 2, grid_size):
            y = i + int(self.offset_y) % grid_size
            if 0 <= y <= height:
                painter.drawLine(0, y, width, y)

    def draw_world_outline(self, painter):
        """绘制简化的世界地图轮廓"""
        painter.setPen(QPen(QColor(100, 150, 200, 80), 2))

        # 绘制一些主要的大陆轮廓（简化版）
        continents = [
            # 亚洲
            [(60, 70), (140, 50), (150, 10), (90, 0), (40, 30), (60, 70)],
            # 欧洲
            [(-10, 70), (40, 60), (30, 35), (-10, 35), (-10, 70)],
            # 北美洲
            [(-140, 70), (-60, 60), (-80, 25), (-120, 30), (-140, 70)],
            # 南美洲
            [(-80, 10), (-35, 5), (-40, -55), (-75, -55), (-80, 10)],
            # 非洲
            [(-20, 35), (50, 35), (40, -35), (15, -35), (-20, 35)],
            # 澳洲
            [(110, -10), (155, -10), (155, -45), (110, -45), (110, -10)]
        ]

        for continent in continents:
            points = []
            for lon, lat in continent:
                x, y = self.coord_to_flat_pixel(lon, lat)
                if 0 <= x <= self.width() and 0 <= y <= self.height():
                    points.append((x, y))

            # 绘制大陆轮廓
            for i in range(len(points) - 1):
                painter.drawLine(points[i][0], points[i][1],
                                 points[i + 1][0], points[i + 1][1])

    def draw_cities(self, painter):
        """绘制主要城市"""
        for city, (lon, lat) in self.major_cities.items():
            x, y = self.coord_to_flat_pixel(lon, lat)

            if 0 <= x <= self.width() and 0 <= y <= self.height():
                # 绘制城市点
                painter.setBrush(QBrush(QColor(100, 200, 255, 200)))
                painter.setPen(QPen(QColor(255, 255, 255, 255), 2))
                painter.drawEllipse(x - 4, y - 4, 8, 8)

                # 绘制城市名称（只显示主要城市）
                if city in ['北京', '纽约', '伦敦', '东京'] and self.scale_factor > 0.8:
                    painter.setPen(QPen(QColor(255, 255, 255, 200)))
                    painter.setFont(QFont("Arial", 10))
                    painter.drawText(x + 8, y - 3, city)

    def draw_connections(self, painter):
        """绘制网络连接"""
        if not self.connections:
            # 如果没有连接，显示提示信息
            painter.setPen(QPen(QColor(255, 255, 255, 150)))
            painter.setFont(QFont("Arial", 14))
            text_rect = self.rect()
            painter.drawText(text_rect, Qt.AlignmentFlag.AlignCenter, "暂无网络连接数据\n等待数据加载...")
            return

        # 北京作为默认源点
        source_x, source_y = self.coord_to_flat_pixel(116.4074, 39.9042)

        # 限制显示的连接数量
        display_connections = self.connections[:8]

        for i, conn in enumerate(display_connections):
            try:
                # 获取目标坐标
                target_lon = conn.get('longitude', 0)
                target_lat = conn.get('latitude', 0)

                # 如果没有地理位置信息，使用随机城市
                if target_lon == 0 and target_lat == 0:
                    city_coords = random.choice(list(self.major_cities.values()))
                    target_lon, target_lat = city_coords

                target_x, target_y = self.coord_to_flat_pixel(target_lon, target_lat)

                # 确保坐标在画布范围内
                if not (0 <= target_x <= self.width() and 0 <= target_y <= self.height()):
                    continue

                # 设置连接线样式
                if conn.get('status') == 'ESTABLISHED':
                    line_color = QColor(0, 255, 100, 150)  # 绿色表示活跃连接
                    dot_color = QColor(0, 255, 100, 200)
                else:
                    line_color = QColor(255, 100, 100, 120)  # 红色表示断开连接
                    dot_color = QColor(255, 100, 100, 180)

                # 绘制连接线
                painter.setPen(QPen(line_color, 2))
                painter.drawLine(source_x, source_y, target_x, target_y)

                # 绘制动画效果
                if i < 4:  # 只为前4个连接显示动画
                    progress = (self.animation_phase + i * 10) % 60 / 60.0
                    anim_x = source_x + (target_x - source_x) * progress
                    anim_y = source_y + (target_y - source_y) * progress

                    # 绘制移动的光点
                    painter.setBrush(QBrush(dot_color))
                    painter.setPen(Qt.PenStyle.NoPen)
                    painter.drawEllipse(int(anim_x - 3), int(anim_y - 3), 6, 6)

                # 绘制目标点
                painter.setBrush(QBrush(QColor(255, 255, 0, 180)))
                painter.setPen(QPen(QColor(255, 255, 255, 200), 1))
                painter.drawEllipse(target_x - 4, target_y - 4, 8, 8)

                # 显示连接信息
                if self.scale_factor > 1.2:  # 只在放大时显示详细信息
                    city = conn.get('city', '未知')
                    if city != '未知' and len(city) < 10:
                        painter.setPen(QPen(QColor(255, 255, 255, 180)))
                        painter.setFont(QFont("Arial", 9))
                        painter.drawText(target_x + 8, target_y + 12, city)

            except Exception as e:
                print(f"绘制连接时出错: {e}")
                continue

    def draw_controls_info(self, painter):
        """绘制控制信息"""
        # 绘制连接统计信息
        mode_text = "🌍 球体模式" if self.sphere_mode else "🗺️ 平面模式"
        info_text = f"{mode_text} | 缩放: {self.scale_factor:.1f}x | 连接: {len(self.connections)}"

        painter.setPen(QPen(QColor(255, 255, 255, 200)))
        painter.setFont(QFont("Arial", 11, QFont.Weight.Bold))
        painter.drawText(10, 25, info_text)

        # 绘制操作提示
        controls_text = "滚轮缩放 | 拖拽移动 | 双击重置"
        painter.setPen(QPen(QColor(255, 255, 255, 150)))
        painter.setFont(QFont("Arial", 9))
        painter.drawText(10, self.height() - 10, controls_text)

        # 绘制图例
        legend_y = self.height() - 35

        # 活跃连接图例
        painter.setBrush(QBrush(QColor(0, 255, 100, 150)))
        painter.setPen(Qt.PenStyle.NoPen)
        painter.drawEllipse(10, legend_y, 8, 8)
        painter.setPen(QPen(QColor(255, 255, 255, 180)))
        painter.setFont(QFont("Arial", 9))
        painter.drawText(25, legend_y + 8, "活跃")

        # 断开连接图例
        painter.setBrush(QBrush(QColor(255, 100, 100, 150)))
        painter.setPen(Qt.PenStyle.NoPen)
        painter.drawEllipse(70, legend_y, 8, 8)
        painter.setPen(QPen(QColor(255, 255, 255, 180)))
        painter.drawText(85, legend_y + 8, "断开")

        # 目标节点图例
        painter.setBrush(QBrush(QColor(255, 255, 0, 180)))
        painter.setPen(Qt.PenStyle.NoPen)
        painter.drawEllipse(130, legend_y, 8, 8)
        painter.setPen(QPen(QColor(255, 255, 255, 180)))
        painter.drawText(145, legend_y + 8, "节点")

    def resizeEvent(self, event):
        """窗口大小改变时重新绘制"""
        super().resizeEvent(event)
        self.update()
